#!/bin/bash
#
# Copyright 2015-2017 Adrian DC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# === ADB MultiROM Selector ===
function adbmromselect()
{
  # Usage: adbmromselect [preselect] (Select MultiROM installation for path)

  # Variables
  local cnt;
  local enforced;
  local key;
  local options;
  local preselect=${1};
  local path;
  local roms;

  # Verify adb is ready
  adbready;

  # Prepare selinux access
  enforced=$(adbsu 'getenforce');
  if [ "${enforced}" = 'Enforcing' ]; then
    adbsu 'setenforce 0';
  fi;

  # List all MultiROM installations
  roms=$(mktemp);
  adbsu 'find /sdcard/MultiROM/multirom/roms/* /sdcard/multirom/roms/* /sdcard1/multirom-*/* /external_sd/multirom-*/* /data/media/0/external_multirom/multirom-*/* /data/media/0/MultiROM/external/multirom-*/* -maxdepth 0 -type d 2> /dev/null' \
      | grep -v '/sdcard/MultiROM/multirom/roms/Internal' \
      | grep -v '/sdcard/multirom/roms/Internal' \
      > "${roms}";

  # Restore selinux access
  if [ "${enforced}" = 'Enforcing' ]; then
    adbsu 'setenforce 1';
  fi;

  # Create ROMs selector list
  cnt=0;
  options=('None');
  path=;
  >&2 echo '';
  >&2 echo -e " \e[1;37m[ Select MultiROM installation ]\e[0m";
  >&2 echo '';
  >&2 echo "   ${cnt}: ${options[${cnt}]}";
  while read -r path; do
    cnt=$((cnt + 1));
    options[${cnt}]=${path};
    >&2 echo "   ${cnt}: ${options[${cnt}]}";
  done < "${roms}";
  >&2 echo '';
  >&2 echo -en " \e[1;33mROM to use [0 to ${cnt}] :\e[0m ";
  if [ -z "${preselect}" ]; then
    >&2 read -r key;
  else
    >&2 echo "${preselect}";
    key=${preselect};
  fi;
  >&2 echo '';

  # Return selected ROM path
  if [ "${key}" -gt 0 ] && [ "${key}" -le "${cnt}" ]; then
    echo -n "${options[${key}]}" | tr -d '\r';
  fi;

  # Cleanup temporary files
  rm -f "${roms}";
}

# === ADB MultiROM Bootimage Installer ===
function adbmrombootimage()
{
  # Variables
  local boot_extracted_files;
  local filepath=${1};
  local filedir;
  local partitiontarget;
  local preselect=${2};
  local romdir;
  local romtarget;

  # Detect bootimage file
  if [ -z "${filepath}" ]; then
    if [ -f 'boot.img' ]; then
      filepath=boot.img;
    fi;
  fi;

  # Usage
  if [ -z "${filepath}" ] || [ ! -f "${filepath}" ]; then
    echo '';
    echo '  Usage: adbmrombootimage <bootimage_path> [preselect] (MultiROM bootimage installer)';
    echo '';
    return;
  fi;

  # Verify adb is ready
  adbready;

  # Get ROM and bootimage
  partitiontarget=$(androiddevicestarget boot);
  romdir=$(adbmromselect "${preselect}");
  romtarget=${romdir}/boot.img;

  # Abort on missing ROM directory
  if [ -z "${romdir}" ]; then
    echo '';
    echo '  adbmrombootimage: Improper ROM path selection';
    echo '';
    return;
  fi;

  # Load ROM bootimage to partition
  echo " Injecting '${romtarget}' to '${partitiontarget}'";
  echo '';
  adbro;
  adbsu "dd if=\"${partitiontarget}\" of=/sdcard/boot.dump";

  # Files to device push
  adb push "${filepath}" '/sdcard/boot.mrom';

  # Bootimage injection
  adbsu "dd if=/dev/zero of=\"${partitiontarget}\";
         dd if=/sdcard/boot.mrom of=\"${partitiontarget}\";
         rm -f /sdcard/boot.mrom" \
      | grep -v 'No space left on device';

  # Restore ROM bootimage to partition
  echo '';
  echo " Restoring '${partitiontarget}' to '${romtarget}'";
  echo '';
  adbsu "dd if=\"${partitiontarget}\" of=\"${romtarget}\";
         dd if=/sdcard/boot.dump of=\"${partitiontarget}\";
         rm -f /sdcard/boot.dump";
  echo '';

  # Check if filepath has built extracted files
  filedir=$(dirname "${filepath}");

  # Read all boot extracted files
  boot_extracted_files=$(adbsu "ls \"${romdir}/boot\"");

  # Replace extracted files with new ones
  for file in ${boot_extracted_files}; do
    if [ -f "${filedir}/root/${file}" ] && [ ! -L "${filedir}/root/${file}" ]; then
      adb push "${filedir}/root/${file}" "/tmp/${file}";
      adbsu "cp \"/tmp/${file}\" \"${romdir}/boot/${file}\";
             rm -f \"/tmp/${file}\";";
    fi;
  done;
  echo '';
}

# === ADB MultiROM Kernel Injector ===
function adbmrominjector()
{
  # Variables
  local filepath=${1};
  local preselect=${2};

  # Detect zImage file
  if [ -z "${filepath}" ]; then
    if [ -f '.build/arch/arm64/boot/zImage' ]; then
      filepath=.build/arch/arm64/boot/zImage;
    elif [ -f '.build/arch/arm/boot/zImage' ]; then
      filepath=.build/arch/arm/boot/zImage;
    elif [ -f 'arch/arm64/boot/zImage' ]; then
      filepath=arch/arm64/boot/zImage;
    elif [ -f 'arch/arm/boot/zImage' ]; then
      filepath=arch/arm/boot/zImage;
    fi;
  fi;

  # Usage
  if [ -z "${filepath}" ] || [ ! -f "${filepath}" ]; then
    echo '';
    echo '  Usage: adbmrominjector <kernel_path> (MultiROM kernel image injector)';
    echo '';
    return;
  fi;

  # Variables
  local partitiontarget;
  local romtarget;

  # Verify adb is ready
  adbready;

  # Get ROM and bootimage
  partitiontarget=$(androiddevicestarget boot);
  romtarget=$(adbmromselect "${preselect}")/boot.img;

  # Abort on missing ROM directory
  if [ -z "${partitiontarget}" ]; then
    echo '';
    echo '  adbmrominjector: Improper ROM path selection';
    echo '';
    return;
  fi;

  # Load ROM bootimage to partition
  echo " Injecting '${romtarget}' to '${partitiontarget}'";
  echo '';
  adbro;
  adbsu "dd if=\"${partitiontarget}\" of=/sdcard/boot.dump;
         dd if=\"${romtarget}\" of=\"${partitiontarget}\"";

  # Files to device push=
  adb push "${filepath}" '/tmp/tmpkernel';
  adb push "${ANDROID_DEVELOPMENT_SHELL_TOOLS_BBOOTIMG}" '/tmp/bbootimg';
  adbsu 'chmod +x /tmp/bbootimg;
         chmod 755 /tmp/bbootimg';

  # Kernel injection
  adbsu "/tmp/bbootimg -i \"${partitiontarget}\";
         /tmp/bbootimg -u \"${partitiontarget}\" -k /tmp/tmpkernel;
         rm -f /tmp/bbootimg /tmp/tmpkernel";

  # Restore ROM bootimage to partition
  echo '';
  echo " Restoring '${partitiontarget}' to '${romtarget}'";
  echo '';
  adbsu "dd if=\"${partitiontarget}\" of=\"${romtarget}\";
         dd if=/sdcard/boot.dump of=\"${partitiontarget}\";
         rm -f /sdcard/boot.dump";
  echo '';
}

# === ADB MultiROM AutoBoot ===
function adbmromautoboot()
{
  # Usage: adbmromautoboot (MultiROM autoboot selection)

  # Variables
  local romtarget;
  local preselect=${2};

  # Read multirom.ini
  echo '';
  adbsu "cat /data/media/0/MultiROM/multirom/multirom.ini >/dev/null 2>&1;
         cat /data/media/0/multirom/multirom.ini >/dev/null 2>&1;";

  # Verify adb is ready
  adbready;

  # Get ROM
  romtarget=$(adbmromselect "${preselect}");

  # Abort on missing ROM directory
  if [ -z "${romtarget}" ]; then
    echo '';
    echo '  adbmromautoboot: Improper ROM path selection';
    echo '';
    return;
  fi;

  # Modify multirom.ini
  adbsu "sed -i 's#auto_boot_rom=.*#auto_boot_rom=${romtarget##*/}#' /data/media/0/MultiROM/multirom/multirom.ini;
         sed -i 's#auto_boot_rom=.*#auto_boot_rom=${romtarget##*/}#' /data/media/0/multirom/multirom.ini;
         sed -i 's#current_rom=.*#current_rom=${romtarget##*/}#' /data/media/0/MultiROM/multirom/multirom.ini;
         sed -i 's#current_rom=.*#current_rom=${romtarget##*/}#' /data/media/0/multirom/multirom.ini;
         cat /data/media/0/MultiROM/multirom/multirom.ini;
         cat /data/media/0/multirom/multirom.ini;";

  # Reboot to Android
  adb reboot;
  echo '';
}

# === ADB MultiROM File Editor ===
function adbmromedit()
{
  # Variables
  local filepath=${1};
  local preselect=${2};

  # Usage
  if [ -z "${filepath}" ]; then
    echo '';
    echo '  Usage: adbmromedit <relative_path> [preselect] (MultiROM secondary ROM file editor)';
    echo '';
    return;
  fi;

  # Variables
  local romtarget;

  # Verify adb is ready
  adbready;

  # Get ROM path
  romtarget=$(adbmromselect "${preselect}");

  # Abort on missing ROM directory
  if [ -z "${romtarget}" ]; then
    echo '';
    echo '  adbmromedit: Improper ROM path selection';
    echo '';
    return;
  fi;

  # Edit given file path
  echo -e " \e[1;37madbmromedit: Editing '${romtarget}/${filepath#/}'\e[0m";
  echo '';
  adbedit "${romtarget}/${filepath#/}";
  echo '';
}
